/*
 * Copyright (c) 2023 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "i_mock_chip.h"

namespace mock_chip {

std::vector<uint8_t> Interface_Chip_mock::BlockIORead(const uint32_t& offset,
                                                      const uint32_t& length) {
    return std::vector<uint8_t>();
}

void Interface_Chip_mock::BlockIOWrite(const uint32_t& offset, const std::vector<uint8_t>& buffer) {
    return;
}

std::vector<uint8_t> Interface_Chip_mock::BlockIOComboWriteRead(
    const uint32_t& write_offset, const std::vector<uint8_t>& write_buffer,
    const uint32_t& read_offset, const uint32_t& read_length) {
    // 根据offset 还有opcode进行打桩
    uint16_t opcode = (write_buffer[4] << 8) | write_buffer[3]; // opcode 为 0x0005
    if (opcode == 0x0010) {
        std::vector<uint8_t> rsp = {0x0C, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C};
        for (int i = rsp.size(); i < 66; i++) {
            rsp.push_back(0x00);
        }
        return rsp;
    } else if (opcode == 0x0404) {
        std::vector<uint8_t> rsp = {0x15, 0x00, 0x00, 0x04, 0x04, 0x2D, 0x00, 0x00,
                                    0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x10,
                                    0x00, 0x15, 0x5D, 0x50, 0x36, 0x14, 0x2C};
        for (int i = rsp.size(); i < 66; i++) {
            rsp.push_back(0x00);
        }
        return rsp;
    } else if (opcode == 0x0050) {
        // 这个需要传入带有arg=5的request
        std::vector<uint8_t> rsp = {
            0x10, 0x00, 0x00, 0x50, 0x00, 0x04, 0x00, 0x00, 0x00,
            0x04, 0x00, 0x00, 0x00, 0x74, 0x72, 0x75, 0x65, // 这四个十六进制转换为字符串为  "true"
            0xC2};
        for (int i = rsp.size(); i < 66; i++) {
            rsp.push_back(0x00);
        }
        return rsp;
    }
    return std::vector<uint8_t>();
}

std::vector<uint8_t> Interface_Chip_mock::BlockIOWriteRead(const std::vector<uint8_t>& indata,
                                                           const uint32_t& read_length) {
    // 根据opcode 和 data进行打桩
    // data的一个样例为 0x00 0x00 0x05 0x00 0x00 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x04 0x57 0xd8
    // 0x14 根据其中的第3个和第4个字节组成的opcode进行返回
    uint16_t opcode = (indata[3] << 8) | indata[2]; // opcode 为 0x0005
    if (opcode == 0x02) {
        // FaultCode
        std::vector<uint8_t> rsp = {
            0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x48, 0x8A, 0x9F};
        return rsp;
    }
    if (opcode == 0x0005) {
        // 返回固件版本号 对应固件版本号为 17.6.9.2
        std::vector<uint8_t> rsp = {0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
                                    0x00, 0x00, 0x11, 0x45, 0x02, 0x21, 0x29, 0xEF, 0xA4};
        // 剩下的用0xFF填充
        for (int i = rsp.size(); i < 64; i++) {
            rsp.push_back(0xFF);
        }
        return rsp;
    } else if (opcode == 0x104) {
        return std::vector<uint8_t>{0x00, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
                                    0x00, 0x00, 0x10, 0x01, 0x24, 0x35, 0xA8, 0x3E, 0xFF, 0xFF,
                                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    } else if (opcode == 0x0404 && read_length == 64) {
        // 返回mac地址  port -> 0 , PV_VF -> 0x0000 , mac_addr -> ac:dc:ca:5e:11:c9
        return std::vector<uint8_t>{
            0x00, 0x00, 0x04, 0x04, 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xAC, 0xDC, 0xCA, 0x5E, 0x11, 0xC9, 0x01, 0x00, 0x01, 0xAC, 0xDC,
            0xCA, 0x5E, 0x11, 0xCA, 0x02, 0x00, 0x02, 0xAC, 0xDC, 0xCA, 0x5E, 0x11, 0xCB,
            0x03, 0x00, 0x03, 0xAC, 0xDC, 0xCA, 0x5E, 0x11, 0xCC, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x9F, 0xEC, 0x41};
    } else if (opcode == 0x400) {
        // 光模块温度
        std::vector<uint8_t> rsp = {
            0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFE,
            0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F,
            0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD,
            0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F,
            0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0xFD, 0x7F, 0x7D, 0x51, 0x83, 0x23};
        return rsp;
    } else if (opcode == 0x03) {
        // network_adapter cooling 温度
        std::vector<uint8_t> rsp = {0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
                                    0x00, 0x00, 0x40, 0x00, 0x30, 0xF1, 0x12, 0x85, 0xFF, 0xFF};
        return rsp;
    } else if (opcode == 0x0403) {
        std::vector<uint8_t> rsp = {
            0x00, 0x00, 0x03, 0x04, 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x06, 0x60, 0x3D};
        return rsp;
    }
    return std::vector<uint8_t>();
}

} // namespace mock_chip

MC_REFLECT(mock_chip::Interface_Chip_mock,
           ((BlockIORead, "BlockIORead"))((BlockIOWrite, "BlockIOWrite"))(
               (BlockIOWriteRead, "BlockIOWriteRead"))((BlockIOComboWriteRead,
                                                        "BlockIOComboWriteRead")))
